using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using DirectShowLib;
using System.Drawing;
using System.IO;


namespace ConsolePlayer
{
	public class SoundPlayer : IPlayerCore
    {
        IFilterGraph2 graphBuilder;
        IMediaSeeking mediaSeeking;
        IMediaControl mediaControl;
        IBasicAudio audioControl;
        IVideoWindow window = null;
        Stack<int> errorStack = new Stack<int>();
        bool isValidate = false;
		IntPtr ownerWnd = IntPtr.Zero;
        public bool Validate
        {
            get { return isValidate; }
        }

        string fileName = string.Empty;
        public SoundPlayer(string file)
        {
            graphBuilder = (new FilterGraph()) as IFilterGraph2;
            if (graphBuilder == null) return;
            mediaControl = graphBuilder as IMediaControl;
            mediaSeeking = graphBuilder as IMediaSeeking;
            audioControl = graphBuilder as IBasicAudio;
            if (mediaControl == null || mediaSeeking == null || audioControl == null) return;
            //int hr = mediaControl.RenderFile(file);
			FileInfo info = new FileInfo(file);
			ISupport support = Supports.Instance[info.Extension];
			int hr = -1;
			if (support != null)
				hr = support.RenderGraph(graphBuilder, file);
			else
				hr = mediaControl.RenderFile(file);

            fileName = file;
            if (hr != 0) errorStack.Push(hr);
            if (hr != 0) return;
            mediaSeeking.SetTimeFormat(TimeFormat.MediaTime);
            isValidate = true;
			window = graphBuilder as IVideoWindow;
			if (window != null)
			{
				int width = 0;
				int height = 0;
				window.get_Width(out width);
				window.get_Height(out height);
				nativeSize = new Size(width, height);
			}
        }
        public bool Play()
        {
            Debug.Assert(isValidate);
            int hr = mediaControl.Run();
            if (hr != 0) errorStack.Push(hr);
            return (hr == 0);
        }
        public bool Stop()
        {
            Debug.Assert(isValidate);
            int hr = mediaControl.Stop();
            this.CurrentPosition = 0;
            if (hr != 0) errorStack.Push(hr);
            window.put_Visible(OABool.False);
            return (hr == 0);
        }
        public bool Pause()
        {
            Debug.Assert(isValidate);
            int hr = mediaControl.Pause();
            if (hr != 0) errorStack.Push(hr);
            return (hr == 0);
        }

        public long CurrentPosition
        {
            get
            {
                Debug.Assert(isValidate);
                long cur = -1;
                int hr = mediaSeeking.GetCurrentPosition(out cur);
                if (hr != 0) errorStack.Push(hr);
                return cur / (10000);
            }
            set
            {
                Debug.Assert(isValidate);
                long stopPosition = -1;
                int hr = mediaSeeking.GetStopPosition(out stopPosition);
                if (hr != 0) errorStack.Push(hr);
                hr = mediaSeeking.SetPositions(value * 10000, AMSeekingSeekingFlags.AbsolutePositioning,
                    stopPosition, AMSeekingSeekingFlags.AbsolutePositioning);
                if (hr != 0) errorStack.Push(hr);
            }
        }
		private Size nativeSize = new Size(0, 0);
		public Size NativeSize
		{
			get
			{
				return nativeSize;
			}
		}

        public void SetOwner(IntPtr ptr, Rectangle rect)
        {
            if (window != null)
            {
				ownerWnd = ptr;
                window.put_Owner(ptr);
				window.put_WindowStyle(WindowStyle.Child);
				window.SetWindowPosition(rect.Left, rect.Top, rect.Width, rect.Height);
				

            }
        }
		public IntPtr GetOwner()
		{
			return ownerWnd;
		}

		private bool full = false;
		public void SetFullScreen(IntPtr msgWnd)
		{
			if( window != null )
			{
				
				if (full)
				{
					window.put_MessageDrain(IntPtr.Zero);
					window.put_FullScreenMode(OABool.False);
					full = false;
				}
				else
				{
					window.put_MessageDrain(msgWnd);
					window.put_FullScreenMode(OABool.True);
					full = true;
				}
			}
		}

		public bool IsVideo()
		{
			OABool b;
			window.get_AutoShow(out b);
			return (b== OABool.True);
		}

        public string CurrentFile
        {
            get
            {
                return fileName;
            }
        }

        public long Duration
        {
            get
            {
                Debug.Assert(isValidate);
                long dur = -1;
                int hr = mediaSeeking.GetDuration(out dur);
                if (hr != 0) errorStack.Push(hr);
                return dur / 10000;
            }
        }

        public double Rate
        {
            get
            {
                Debug.Assert(isValidate);
                double rate = 0.0;
                int hr = mediaSeeking.GetRate(out rate);
                if (hr != 0) errorStack.Push(hr);
                return rate;
            }
            set
            {
                Debug.Assert(isValidate);
                int hr = mediaSeeking.SetRate(value);
                if (hr != 0) errorStack.Push(hr);
            }
        }

        public int Volume
        {
            get
            {
                Debug.Assert(isValidate);
                int volume = 0;
                int hr = audioControl.get_Volume(out volume);
                if (hr != 0) errorStack.Push(hr);
                return volume;
            }
            set
            {
                Debug.Assert(isValidate);
                int hr = audioControl.put_Volume(value);
                if (hr != 0) errorStack.Push(hr);
            }
        }

        public int GetLastErrorCode()
        {
            if (errorStack.Count != 0) return errorStack.Pop();
            else return 0;
        }

    }
}
